package com.dongyimai.oauth.service.impl;

import com.dongyimai.oauth.service.AuthService;
import com.dongyimai.oauth.util.AuthToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.UnknownHttpStatusCodeException;

import javax.sound.midi.Soundbank;
import java.io.IOException;
import java.util.Map;

@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 授权认证方法
     *
     * @param username     用户名
     * @param password     密码
     * @param clientId     客户端口的标识
     * @param clientSecret 客户端口的密钥
     * @return
     */
    @Override
    public AuthToken login(String username, String password, String clientId, String clientSecret) {
        System.out.println("username:" + username + "password:" + password);
        //申请令牌
        AuthToken authToken = this.applyToken(username, password, clientId, clientSecret);
        if (authToken == null) {
            throw new RuntimeException("申请令牌失败");
        }
        return authToken;
    }

    /**
     * 认证方法  发放令牌
     *
     * @param username
     * @param password
     * @param clientId     客户端id
     * @param clientSecret 客户端秘钥
     * @return
     */
    private AuthToken applyToken(String username, String password, String clientId, String clientSecret) {
        // 选中认证服务的地址   http://localhost:10001
        ServiceInstance serviceInstance = loadBalancerClient.choose("user-auth");
        System.out.println("1 选中认证服务的地址 ---serviceInstance" + serviceInstance);
        if (serviceInstance == null){
            throw new RuntimeException("找不到服务！");
        }
        System.out.println("2-----找到服务");
        // 获取请求令牌的地址
        String path = serviceInstance.getUri().toString() + "/oauth/token";
        System.out.println("3 获取请求令牌的地址-----path :" + path);
        // 定义请求体
        MultiValueMap<String ,String > formData = new LinkedMultiValueMap();
        formData.add("grant_type","password");
        formData.add("username",username);
        formData.add("password",password);
        System.out.println("4 定义请求体-----formData:" + formData);
        // 定义请求头
        MultiValueMap<String ,String > header = new LinkedMultiValueMap();
        header.add("Authorization",httpbasic(clientId,clientSecret));
        System.out.println("5-------header:" +header);
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
              // 当响应值为401 / 400  的时候 不需要抛出异常 而正常响应
                if (response.getRawStatusCode() != 400 && response.getRawStatusCode() != 401){
                    super.handleError(response);
                }
            }
        });
        System.out.println("6--------- 异常处理");
        Map map = null;
        try {
            ResponseEntity<Map> responseEntity = restTemplate.exchange(path, HttpMethod.POST,
            new HttpEntity<MultiValueMap<String, String>>(formData, header), Map.class);
            System.out.println("7------responseEntity" + responseEntity);
            // 获取响应数据
            map = responseEntity.getBody();
            System.out.println("8-------" + map);
        } catch (RestClientException e) {
            e.printStackTrace();
        }
        if ( map == null || map.get("access_token") ==null
        || map.get("refresh_token") == null || map.get("jti") ==null){
            throw new RuntimeException("创建令牌失败！！！");
        }
        // 封装数据
        AuthToken authToken = new AuthToken();
        authToken.setAccessToken((String) map.get("access_token"));
        authToken.setRefreshToken((String) map.get("refresh_token"));
        authToken.setJti((String) map.get("jti"));
        System.out.println(authToken.getAccessToken());
        System.out.println(authToken.getRefreshToken());
        System.out.println(authToken.getJti());

        return authToken;
    }

    private String httpbasic(String clientId, String clientSecret) {
        String string = clientId + ":" + clientSecret;
        byte[] encode = Base64Utils.encode(string.getBytes());
        return "Basic " + new String(encode);
    }
}
